/**
 * 2023.11.25 16:10 星期六 晴 锅底部 被凿凹进去了 锅也没刷
 */

import { SetStaticCssTxtFunc, toStringTypeCheck } from '../../global';
import { analysisStyleStack } from './styleFuncs/analysisStyleStack';
import { styleStr2Json } from './styleStr2Json';

let styleEl;

let splitStr = '_';

/**
 * styleFunc 的 静态 css 管理器
 */
let StaticCss = SetStaticCssTxtFunc('styleFunc');

/**
 * style2Json  style String 的 json 格式转换
 */
let styleJson;

/**
 * class 对应字段
 */
let regClass = /[^\w]?\.(?<Classname>.*)/;

/**
 * ID 对应字段
 */
let regID = /[^\w]?#(?<IDName>.*)/;

/**
 * keyframe 对应字段
 */
let regKeyfram = /[^\w]?@keyframes (?<keyframeName>.*)/;

/**
 * 名称标签 性质
 */
// let keyTag = { data: ['ID', 'class_n', 'keyframe'] };
//   ID: {
//     data: ['name', 'path', 'labelTag'],
//     name: undefined,
//     path: [],
//     labelTag: 'ID',
//   },
//   class_n: {
//     data: ['name', 'path', 'labelTag'],
//     name: undefined,
//     path: [],
//     labelTag: 'class',
//   },
//   keyframe: {
//     data: ['name', 'path', 'labelTag'],
//     name: undefined,
//     path: [],
//     labelTag: 'keyframe',
//   },
// };

/**
 * 对应表
 */
let mapName = { data: [] };

/**
 * 映射表
 */
let userName;

/**
 * 对 style 元素标签 进行 操作
 * @param {Element} element styleElement style 标签元素
 *
 * 返回值 解释 : --
 *
 *   有些 函数 需要确立 某一个 确定的 style Element 元素 才能进行下一步操作
 *   因此
 */
function styleElFunc(element) {
  if (element.nodeType != '1' || element.nodeName != 'STYLE') {
    console.log('sorry your element is not a style element');
    return false;
  }
  styleEl = element;

  return { styleClone, availableStyleKey };
}

/**
 * 克隆 style 并返回该元素
 * @param {Element|undefined} styleElement
 * @returns {Element} style Element
 */
function styleClone(styleElement) {
  //   console.log('test');
  if (styleElement == undefined) {
    if (!checkStyleEl()) {
      console.log('sorry you do not have available source Style Element');
      return;
    }
    let IDName = `${styleEl.id}${splitStr}clone`;

    StaticCss(IDName, styleEl.innerHTML);
    // 更改绑定 (id) static_${IDName} == static
    styleEl = document.getElementById(IDName);
    return styleEl;
  } else if (
    styleElement['nodeType'] == 1 &&
    styleElement['nodeName'] == 'STYLE'
  ) {
    StaticCss(`clone_${styleElement.id}`, styleElement.innerHTML);
    return document.getElementById(`static_clone_${styleElement.id}`);
  } else {
    console.log('sorry your arguments[0] is not a STYLE element');
    return false;
  }
}

/**
 * 检测 是否 有 原 style 元素标签
 * @returns boolean  styleEl 有 返回 true
 */
function checkStyleEl() {
  return styleEl == undefined ? false : true;
}

/**
 * 信息提取
 * --
 * 返回 style string 里面的  部分名称 合集 在做修改时 --实时 动态更新
 *
 * 其中包括
 * 对应表 和 映射表 -- (对应表 : 属性对应的 位置 等)  || (映射表 : 属性对应的值)
 *
 * 该函数 返回映射表 给用户 包含 部分名称合集 在用户修改后
 * 并使用函数 进行 一次性更定 会直接修改 当前指定 styleEl 元素标签的内容 (仅限 给定的 部分名称)
 *
 * @param {string|undefined} styleStr style Element.innerHtml
 */
function availableStyleKey(styleStr) {
  if (styleStr == undefined) {
    styleStr = styleEl.innerHTML;
  }
  styleJson = styleStr2Json(styleStr);
  // let nameAllusion={data:[ID]}
  return styleDataNameKey(styleJson);
}

/**
 * 获取 名称对应表 返回 映射表
 * @param {JSON} stylejson style json 解析
 * @returns userName={data:[]}
 */
function styleDataNameKey(stylejson) {
  if (styleJson['$data'] == undefined) {
    return;
  }
  // 备份链接 避免污染信息
  let copyJ = stylejson;
  let kg;

  //   animation name 对应字段 -- animation-name || animation 合集 的名称字段 最后一个 空行

  let keyinfo;
  for (let i = 0; i < copyJ['$data'].length; i++) {
    if ((keyinfo = regID.exec(copyJ['$data'][i]))) {
      kg = keyinfo['groups'];
      mapName['data'].push(kg['IDName']);
      mapName[kg['IDName']] = {
        name: kg['IDName'],
        path: [copyJ['$data'][i]],
        type: 'ID',
      };
    } else if ((keyinfo = regClass.exec(copyJ['$data'][i]))) {
      kg = keyinfo['groups'];
      mapName['data'].push(kg['Classname']);
      mapName[kg['Classname']] = {
        name: kg['Classname'],
        path: [copyJ['$data'][i]],
        type: 'Class',
      };
    } else if ((keyinfo = regKeyfram.exec(copyJ['$data'][i]))) {
      kg = keyinfo['groups'];
      mapName['data'].push(kg['keyframeName']);
      mapName[kg['keyframeName']] = {
        name: kg['keyframeName'],
        path: [copyJ['$data'][i]],
        type: 'Keyframe',
      };
    }
  }
  for (let j = 0; j < copyJ['$data'].length; j++) {
    /**
     * 选择器中的 animation name  (animation: ... [keyframe] ||
     */
    if (copyJ[copyJ['$data'][j]]['$data'].indexOf('animation') > -1) {
      let arr = copyJ[copyJ['$data'][j]]['animation'].split(' ');
      if (mapName[arr[arr.length - 1]] != undefined) {
        mapName[arr[arr.length - 1]]['path'].push(
          copyJ['$data'][j] + splitStr + 'animation'
        );
      }
    }
    /**
     * animation-name: [animation-name])
     */
    if (copyJ[copyJ['$data'][j]]['$data'].indexOf('animation-name') > -1) {
      if (mapName[copyJ[copyJ['$data'][j]]['animation-name']] != undefined) {
        mapName[copyJ[copyJ['$data'][j]]['animation-name']]['path'].push(
          copyJ['$data'][j] + splitStr + 'animation-name'
        );
      }
    }
  }
  userName = { data: [...mapName['data']] };
  //   console.log(mapName);
  //   console.log(userName);
  return userName;
}

/**
 * styleElFunc().availableStyleKey() 对返回信息 进行修改
 *
 * 修改后 使用 entryName("修改内容"--对 data 对应内容 进行属性赋值)
 *
 * 更改 部分名称 返回到 当前元素
 * @param {Object} userName 用户 根据解析出来的 部分名称 进行 赋值 修改
 */
function entryName(userName) {
  let deleteNameArr = [];
  for (let i = 0; i < userName['data'].length; i++) {
    let oldName = userName['data'][i];
    let newName = userName[userName['data'][i]];
    // 如果 没有新名称 直接执行 下一个
    if (newName == undefined) {
      continue;
    }

    // 名称 必须为 字符
    if (toStringTypeCheck(newName, 'string')) {
      // 1.0 修改 自身的 名称指向
      let oldIndex = styleJson['$data'].indexOf(mapName[oldName]['path'][0]);
      let newtypeName = typeName(newName, mapName[oldName]['type']);
      styleJson['$data'].splice(oldIndex, 1, newtypeName);
      // 添加 后续 需要 删除的元素
      deleteNameArr.push(mapName[oldName]['path'][0]);

      // 链接 新内容 的旧内容
      //   let a = styleJson[oldName];
      styleJson[newtypeName] = styleJson[mapName[oldName]['path'][0]];

      // 2.0 修改 keyframe 名称 绑定
      for (let j = 1; j < mapName[oldName]['path'].length; j++) {
        let keyNamearr = mapName[oldName]['path'][j].split(splitStr);
        let oldIndex = keyNamearr
          .splice(0, keyNamearr.length - 1)
          .join(splitStr);
        if (keyNamearr[keyNamearr.length - 1] == 'animation-name') {
          //   mapName[keyNamearr[0]]['animation-name'] = newName;
          styleJson[oldIndex]['animation-name'] = newName;
        }
        if (keyNamearr[keyNamearr.length - 1] == 'animation') {
          //   mapName[keyNamearr[0]]['animation'].replace(oldName, newName);
          styleJson[oldIndex]['animation'].replace(oldName, newName);
        }
      }
    }
  }
  // 删除 原数据
  for (let m = 0; m < deleteNameArr.length; m++) {
    delete styleJson[deleteNameArr[m]];
  }
  // 3.0 组合成 新的 字符 添加到原 style 标签中
  styleEl.innerHTML = analysisStyleStack(styleJson);
}

function typeName(newName, type) {
  //   console.log(newName, type);
  if (type == 'ID') {
    return `#${newName}`;
  } else if (type == 'Class') {
    return `.${newName}`;
  } else if (type == 'Keyframe') {
    return `@keyframes ${newName}`;
  }
}

export { styleElFunc, styleClone, entryName };
